package com.saasovation.collaboration.port.adapter.messaging;

import com.saasovation.common.event.sourcing.DispatchableDomainEvent;
import com.saasovation.common.event.sourcing.EventDispatcher;
import com.saasovation.common.notification.Notification;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;

import static com.saasovation.common.port.adapter.notification.SpringMessageUtils.convertToMessage;

public class SpringRabbitMQEventDispatcher implements EventDispatcher {

    private RabbitTemplate rabbitTemplate;
    private String exchangeName;

    public SpringRabbitMQEventDispatcher(RabbitTemplate rabbitTemplate,
                                         String exchangeName,
                                         EventDispatcher aParentEventDispatcher) {
        setRabbitTemplate(rabbitTemplate);
        setExchangeName(exchangeName);
        aParentEventDispatcher.registerEventDispatcher(this);

    }

    @Override
    public void dispatch(DispatchableDomainEvent aDispatchableDomainEvent) {
        Notification notification = new Notification(aDispatchableDomainEvent.eventId(),
                aDispatchableDomainEvent.domainEvent());
        sendNotification(notification);
    }

    @Override
    public void registerEventDispatcher(EventDispatcher anEventDispatcher) {
        throw new UnsupportedOperationException("Cannot register additional dispatchers.");
    }

    @Override
    public boolean understands(DispatchableDomainEvent aDispatchableDomainEvent) {
        return true;
    }

    private void sendNotification(Notification notification) {
        Message message = convertToMessage(notification);
        rabbitTemplate().convertAndSend(exchangeName(), "", message);
    }

    private void setRabbitTemplate(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }

    private RabbitTemplate rabbitTemplate() {
        return this.rabbitTemplate;
    }

    private void setExchangeName(String exchangeName) {
        this.exchangeName = exchangeName;
    }

    private String exchangeName() {
        return this.exchangeName;
    }
}
